home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / access / transam / varsup.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  16.9 KB  |  636 lines

  1. /* ----------------------------------------------------------------
  2.  *   FILE
  3.  *    varsup.c
  4.  *    
  5.  *   DESCRIPTION
  6.  *    postgres variable relation support routines
  7.  *
  8.  *   INTERFACE ROUTINES
  9.  *    VariableRelationGetNextXid
  10.  *    VariableRelationPutNextXid
  11.  *    VariableRelationGetLastXid
  12.  *    VariableRelationPutLastXid
  13.  *    GetNewTransactionId
  14.  *    UpdateLastCommittedXid
  15.  *       
  16.  *   NOTES
  17.  *    presently debugging new routines for oid generation...
  18.  *
  19.  *    VariableRelationGetNextOid
  20.  *    VariableRelationPutNextOid
  21.  *    GetNewObjectIdBlock
  22.  *    GetNewObjectId
  23.  *
  24.  *   IDENTIFICATION
  25.  *    $Header: /private/postgres/src/access/transam/RCS/varsup.c,v 1.18 1992/05/28 20:20:52 mer Exp $
  26.  * ----------------------------------------------------------------
  27.  */
  28.  
  29. #include <math.h>
  30.  
  31. #include "tmp/postgres.h"
  32.  
  33.  RcsId("$Header: /private/postgres/src/access/transam/RCS/varsup.c,v 1.18 1992/05/28 20:20:52 mer Exp $");
  34.  
  35. #include "machine.h"        /* in port/ directory (needed for BLCKSZ) */
  36.  
  37. #include "storage/buf.h"
  38. #include "storage/bufmgr.h"
  39. #include "storage/ipc.h"    /* for OIDGENLOCKID */
  40.  
  41. #include "utils/rel.h"
  42. #include "utils/log.h"
  43.  
  44. #include "access/heapam.h"
  45. #include "access/transam.h"
  46.  
  47. #include "catalog/catname.h"
  48.  
  49. /* ----------
  50.  *      note: we reserve the first 16384 object ids for internal use.
  51.  *      oid's less than this appear in the .bki files.  the choice of
  52.  *      16384 is completely arbitrary.
  53.  * ----------
  54.  */
  55. #define BootstrapObjectIdData 16384
  56.  
  57. /* ---------------------
  58.  *    spin lock for oid generation
  59.  * ---------------------
  60.  */
  61. int OidGenLockId;
  62.  
  63. /* ----------------------------------------------------------------
  64.  *          variable relation query/update routines
  65.  * ----------------------------------------------------------------
  66.  */
  67.  
  68. /* --------------------------------
  69.  *    VariableRelationGetNextXid
  70.  * --------------------------------
  71.  */
  72. void
  73. VariableRelationGetNextXid(xidP)
  74.     TransactionId *xidP;
  75. {
  76.     Buffer buf;
  77.     VariableRelationContents var;
  78.     
  79.     /* ----------------
  80.      * We assume that a spinlock has been acquire to guarantee
  81.      * exclusive access to the variable relation.
  82.      * ----------------
  83.      */
  84.  
  85.     /* ----------------
  86.      *    do nothing before things are initialized
  87.      * ----------------
  88.      */
  89.     if (! RelationIsValid(VariableRelation))
  90.     return;
  91.  
  92.     /* ----------------
  93.      *    read the variable page, get the the nextXid field and
  94.      *  release the buffer
  95.      * ----------------
  96.      */
  97.     buf = ReadBuffer(VariableRelation, 0);
  98.  
  99.     if (! BufferIsValid(buf))
  100.     {
  101.     SpinRelease(OidGenLockId);
  102.     elog(WARN, "VariableRelationGetNextXid: ReadBuffer failed");
  103.     }
  104.  
  105.     var = (VariableRelationContents) BufferGetBlock(buf);
  106.  
  107.     TransactionIdStore(var->nextXidData, xidP);
  108.     ReleaseBuffer(buf);
  109. }
  110.  
  111. /* --------------------------------
  112.  *    VariableRelationGetLastXid
  113.  * --------------------------------
  114.  */
  115. void
  116. VariableRelationGetLastXid(xidP)
  117.     TransactionId *xidP;
  118. {
  119.     Buffer buf;
  120.     VariableRelationContents var;
  121.     
  122.     /* ----------------
  123.      * We assume that a spinlock has been acquire to guarantee
  124.      * exclusive access to the variable relation.
  125.      * ----------------
  126.      */
  127.  
  128.     /* ----------------
  129.      *    do nothing before things are initialized
  130.      * ----------------
  131.      */
  132.     if (! RelationIsValid(VariableRelation))
  133.     return;
  134.  
  135.     /* ----------------
  136.      *    read the variable page, get the the lastXid field and
  137.      *  release the buffer
  138.      * ----------------
  139.      */
  140.     buf = ReadBuffer(VariableRelation, 0);
  141.  
  142.     if (! BufferIsValid(buf))
  143.     {
  144.     SpinRelease(OidGenLockId);
  145.     elog(WARN, "VariableRelationGetNextXid: ReadBuffer failed");
  146.     }
  147.  
  148.     var = (VariableRelationContents) BufferGetBlock(buf);
  149.  
  150.     TransactionIdStore(var->lastXidData, xidP);
  151.  
  152.     ReleaseBuffer(buf);
  153. }
  154.  
  155. /* --------------------------------
  156.  *    VariableRelationPutNextXid
  157.  * --------------------------------
  158.  */
  159. void
  160. VariableRelationPutNextXid(xid)
  161.     TransactionId xid;
  162. {
  163.     Buffer buf;
  164.     VariableRelationContents var;
  165.     
  166.     /* ----------------
  167.      * We assume that a spinlock has been acquire to guarantee
  168.      * exclusive access to the variable relation.
  169.      * ----------------
  170.      */
  171.  
  172.     /* ----------------
  173.      *    do nothing before things are initialized
  174.      * ----------------
  175.      */
  176.     if (! RelationIsValid(VariableRelation))
  177.     return;
  178.  
  179.     /* ----------------
  180.      *    read the variable page, update the nextXid field and
  181.      *  write the page back out to disk.
  182.      * ----------------
  183.      */
  184.     buf = ReadBuffer(VariableRelation, 0);
  185.  
  186.     if (! BufferIsValid(buf))
  187.     {
  188.     SpinRelease(OidGenLockId);
  189.     elog(WARN, "VariableRelationPutNextXid: ReadBuffer failed");
  190.     }
  191.  
  192.     var = (VariableRelationContents) BufferGetBlock(buf);
  193.  
  194.     TransactionIdStore(xid, &(var->nextXidData));
  195.  
  196.     WriteBuffer(buf);
  197. }
  198.  
  199. /* --------------------------------
  200.  *    VariableRelationPutLastXid
  201.  * --------------------------------
  202.  */
  203. void
  204. VariableRelationPutLastXid(xid)
  205.     TransactionId xid;
  206. {
  207.     Buffer buf;
  208.     VariableRelationContents var;
  209.     
  210.     /* ----------------
  211.      * We assume that a spinlock has been acquire to guarantee
  212.      * exclusive access to the variable relation.
  213.      * ----------------
  214.      */
  215.  
  216.     /* ----------------
  217.      *    do nothing before things are initialized
  218.      * ----------------
  219.      */
  220.     if (! RelationIsValid(VariableRelation))
  221.     return;
  222.  
  223.     /* ----------------
  224.      *    read the variable page, update the lastXid field and
  225.      *  force the page back out to disk.
  226.      * ----------------
  227.      */
  228.     buf = ReadBuffer(VariableRelation, 0);
  229.  
  230.     if (! BufferIsValid(buf))
  231.     {
  232.     SpinRelease(OidGenLockId);
  233.     elog(WARN, "VariableRelationPutLastXid: ReadBuffer failed");
  234.     }
  235.  
  236.     var = (VariableRelationContents) BufferGetBlock(buf);
  237.  
  238.     TransactionIdStore(xid, &(var->lastXidData));
  239.  
  240.     WriteBuffer(buf);
  241. }
  242.  
  243. /* --------------------------------
  244.  *    VariableRelationGetNextOid
  245.  * --------------------------------
  246.  */
  247. void
  248. VariableRelationGetNextOid(oid_return)
  249.     oid *oid_return;
  250. {
  251.     Buffer buf;
  252.     VariableRelationContents var;
  253.     
  254.     /* ----------------
  255.      * We assume that a spinlock has been acquire to guarantee
  256.      * exclusive access to the variable relation.
  257.      * ----------------
  258.      */
  259.  
  260.     /* ----------------
  261.      *    if the variable relation is not initialized, then we
  262.      *  assume we are running at bootstrap time and so we return
  263.      *  an invalid object id -- during this time GetNextBootstrapObjectId
  264.      *  should be called instead..
  265.      * ----------------
  266.      */
  267.     if (! RelationIsValid(VariableRelation)) {
  268.     if (PointerIsValid(oid_return))
  269.         (*oid_return) = InvalidObjectId;
  270.     return;
  271.     }
  272.     
  273.     /* ----------------
  274.      *    read the variable page, get the the nextOid field and
  275.      *  release the buffer
  276.      * ----------------
  277.      */
  278.     buf = ReadBuffer(VariableRelation, 0);
  279.  
  280.     if (! BufferIsValid(buf))
  281.     {
  282.     SpinRelease(OidGenLockId);
  283.     elog(WARN, "VariableRelationGetNextXid: ReadBuffer failed");
  284.     }
  285.  
  286.     var = (VariableRelationContents) BufferGetBlock(buf);
  287.  
  288.     if (PointerIsValid(oid_return)) {
  289.  
  290.         /* ----------------
  291.          * nothing up my sleeve...  what's going on here is that this code
  292.      * is guaranteed never to be called until all files in data/base/
  293.      * are created, and the template database exists.  at that point,
  294.      * we want to append a pg_database tuple.  the first time we do
  295.      * this, the oid stored in pg_variable will be bogus, so we use
  296.      * a bootstrap value defined at the top of this file.
  297.      *
  298.      * this comment no longer holds true.  This code is called before
  299.      * all of the files in data/base are created and you can't rely
  300.      * on system oid's to be less than BootstrapObjectIdData. mer 9/18/91
  301.          * ----------------
  302.          */
  303.     if (ObjectIdIsValid(var->nextOid))
  304.         (*oid_return) = var->nextOid;
  305.     else
  306.         (*oid_return) = BootstrapObjectIdData;
  307.     }
  308.  
  309.     ReleaseBuffer(buf);
  310. }
  311.  
  312. /* --------------------------------
  313.  *    VariableRelationPutNextOid
  314.  * --------------------------------
  315.  */
  316. void
  317. VariableRelationPutNextOid(oidP)
  318.     oid *oidP;
  319. {
  320.     Buffer buf;
  321.     VariableRelationContents var;
  322.     
  323.     /* ----------------
  324.      * We assume that a spinlock has been acquire to guarantee
  325.      * exclusive access to the variable relation.
  326.      * ----------------
  327.      */
  328.  
  329.     /* ----------------
  330.      *    do nothing before things are initialized
  331.      * ----------------
  332.      */
  333.     if (! RelationIsValid(VariableRelation))
  334.     return;
  335.  
  336.     /* ----------------
  337.      *    sanity check
  338.      * ----------------
  339.      */
  340.     if (! PointerIsValid(oidP))
  341.     {
  342.     SpinRelease(OidGenLockId);
  343.     elog(WARN, "VariableRelationPutNextOid: invalid oid pointer");
  344.     }
  345.     
  346.     /* ----------------
  347.      *    read the variable page, update the nextXid field and
  348.      *  write the page back out to disk.
  349.      * ----------------
  350.      */
  351.     buf = ReadBuffer(VariableRelation, 0);
  352.  
  353.     if (! BufferIsValid(buf))
  354.     {
  355.     SpinRelease(OidGenLockId);
  356.     elog(WARN, "VariableRelationPutNextXid: ReadBuffer failed");
  357.     }
  358.  
  359.     var = (VariableRelationContents) BufferGetBlock(buf);
  360.  
  361.     var->nextOid = (*oidP);
  362.  
  363.     WriteBuffer(buf);
  364. }
  365.  
  366. /* ----------------------------------------------------------------
  367.  *        transaction id generation support
  368.  * ----------------------------------------------------------------
  369.  */
  370.  
  371. /* ----------------
  372.  *    GetNewTransactionId
  373.  *
  374.  *    In the version 2 transaction system, transaction id's are
  375.  *    restricted in several ways.
  376.  *
  377.  *    First, all transaction id's are even numbers (4, 88, 121342, etc).
  378.  *    This means the binary representation of the number will never
  379.  *    have the least significent bit set.  This bit is reserved to
  380.  *    indicate that the transaction id does not in fact hold an XID,
  381.  *    but rather a commit time.  This makes it possible for the
  382.  *    vaccuum daemon to disgard information from the log and time
  383.  *    relations for committed tuples.  This is important when archiving
  384.  *    tuples to an optical disk because tuples with commit times
  385.  *    stored in their xid fields will not need to consult the log
  386.  *    and time relations.
  387.  *
  388.  *    Second, since we may someday preform compression of the data
  389.  *    in the log and time relations, we cause the numbering of the
  390.  *    transaction ids to begin at 512.  This means that some space
  391.  *    on the page of the log and time relations corresponding to
  392.  *    transaction id's 0 - 510 will never be used.  This space is
  393.  *    in fact used to store the version number of the postgres
  394.  *    transaction log and will someday store compression information
  395.  *    about the log.
  396.  *
  397.  *    Lastly, rather then access the variable relation each time
  398.  *    a backend requests a new transction id, we "prefetch" 32
  399.  *    transaction id's by incrementing the nextXid stored in the
  400.  *    var relation by 64 (remember only even xid's are legal) and then
  401.  *    returning these id's one at a time until they are exhausted.
  402.  *      This means we reduce the number of accesses to the variable
  403.  *    relation by 32 for each backend.
  404.  *
  405.  *      Note:  32 has no special significance.  We don't want the
  406.  *           number to be too large because if when the backend
  407.  *           terminates, we lose the xid's we cached.
  408.  *
  409.  * ----------------
  410.  */
  411.  
  412. #define VAR_XID_PREFETCH    32
  413.  
  414. static int prefetched_xid_count = 0;
  415. TransactionId next_prefetched_xid;
  416.  
  417. void
  418. GetNewTransactionId(xid)
  419.     TransactionId *xid;
  420. {
  421.     TransactionId nextid;
  422.  
  423.     /* ----------------
  424.      *    during bootstrap initialization, we return the special
  425.      *  bootstrap transaction id.
  426.      * ----------------
  427.      */
  428.     if (AMI_OVERRIDE) {    
  429.     TransactionIdStore(AmiTransactionId, xid);
  430.     return;
  431.     }
  432.  
  433.     /* ----------------
  434.      *  if we run out of prefetched xids, then we get some
  435.      *  more before handing them out to the caller.
  436.      * ----------------
  437.      */
  438.     
  439.     if (prefetched_xid_count == 0) {
  440.     /* ----------------
  441.      *    obtain exclusive access to the variable relation page
  442.      *
  443.      *    get the "next" xid from the variable relation
  444.      *    and save it in the prefetched id.
  445.      * ----------------
  446.      */
  447.     SpinAcquire(OidGenLockId);
  448.     VariableRelationGetNextXid(&nextid);
  449.     TransactionIdStore(nextid, &next_prefetched_xid);
  450.     
  451.     /* ----------------
  452.      *    now increment the variable relation's next xid
  453.      *    and reset the prefetched_xid_count.  We multiply
  454.      *    the id by two because our xid's are always even.
  455.      * ----------------
  456.      */
  457.     prefetched_xid_count = VAR_XID_PREFETCH;
  458.     TransactionIdAdd(&nextid, prefetched_xid_count);
  459.     VariableRelationPutNextXid(nextid);
  460.     SpinRelease(OidGenLockId);
  461.     }
  462.     
  463.     /* ----------------
  464.      *    return the next prefetched xid in the pointer passed by
  465.      *  the user and decrement the prefetch count.  We add two
  466.      *  to id we return the next time this is called because our
  467.      *    transaction ids are always even.
  468.      *
  469.      *  XXX Transaction Ids used to be even as the low order bit was
  470.      *      used to determine commit status.  This is no long true so
  471.      *      we now use even and odd transaction ids. -mer 5/26/92
  472.      * ----------------
  473.      */
  474.     TransactionIdStore(next_prefetched_xid, xid);
  475.     TransactionIdAdd(&next_prefetched_xid, 1);
  476.     prefetched_xid_count--;
  477. }
  478.  
  479. /* ----------------
  480.  *    UpdateLastCommittedXid
  481.  * ----------------
  482.  */
  483.  
  484. void
  485. UpdateLastCommittedXid(xid)
  486.     TransactionId xid;
  487. {
  488.     TransactionId lastid;
  489.  
  490.  
  491.     /* we assume that spinlock OidGenLockId has been acquired
  492.      * prior to entering this function
  493.      */
  494.  
  495.     /* ----------------
  496.      *    get the "last committed" transaction id from
  497.      *  the variable relation page.
  498.      * ----------------
  499.      */
  500.     VariableRelationGetLastXid(&lastid);
  501.  
  502.     /* ----------------
  503.      *    if the transaction id is greater than the last committed
  504.      *  transaction then we update the last committed transaction
  505.      *  in the variable relation.
  506.      * ----------------
  507.      */
  508.     if (TransactionIdIsLessThan(lastid, xid))
  509.     VariableRelationPutLastXid(xid);
  510.  
  511. }
  512.  
  513. /* ----------------------------------------------------------------
  514.  *            object id generation support
  515.  * ----------------------------------------------------------------
  516.  */
  517.  
  518. /* ----------------
  519.  *    GetNewObjectIdBlock
  520.  *
  521.  *    This support function is used to allocate a block of object ids
  522.  *    of the given size.  applications wishing to do their own object
  523.  *    id assignments should use this 
  524.  * ----------------
  525.  */
  526.  
  527. void
  528. GetNewObjectIdBlock(oid_return, oid_block_size)
  529.     oid *oid_return;        /* place to return the new object id */
  530.     int oid_block_size;        /* number of oids desired */
  531. {
  532.     oid nextoid;        
  533.  
  534.     /* ----------------
  535.      *    SOMEDAY obtain exclusive access to the variable relation page
  536.      *  That someday is today -mer 6 Aug 1992
  537.      * ----------------
  538.      */
  539.     SpinAcquire(OidGenLockId);
  540.     
  541.     /* ----------------
  542.      *    get the "next" oid from the variable relation
  543.      *    and give it to the caller.
  544.      * ----------------
  545.      */
  546.     VariableRelationGetNextOid(&nextoid);
  547.     if (PointerIsValid(oid_return))
  548.     (*oid_return) = nextoid;
  549.     
  550.     /* ----------------
  551.      *    now increment the variable relation's next oid
  552.      *    field by the size of the oid block requested.
  553.      * ----------------
  554.      */
  555.     nextoid += oid_block_size;
  556.     VariableRelationPutNextOid(&nextoid);
  557.     
  558.     /* ----------------
  559.      *    SOMEDAY relinquish our lock on the variable relation page
  560.      *  That someday is today -mer 6 Apr 1992
  561.      * ----------------
  562.      */
  563.     SpinRelease(OidGenLockId);
  564. }
  565.  
  566. /* ----------------
  567.  *    GetNewObjectId
  568.  *
  569.  *    This function allocates and parses out object ids.  Like
  570.  *    GetNewTransactionId(), it "prefetches" 32 object ids by
  571.  *    incrementing the nextOid stored in the var relation by 32 and then
  572.  *    returning these id's one at a time until they are exhausted.
  573.  *      This means we reduce the number of accesses to the variable
  574.  *    relation by 32 for each backend.
  575.  *
  576.  *      Note:  32 has no special significance.  We don't want the
  577.  *           number to be too large because if when the backend
  578.  *           terminates, we lose the oids we cached.
  579.  *
  580.  * ----------------
  581.  */
  582.  
  583. #define VAR_OID_PREFETCH    32
  584.  
  585. int prefetched_oid_count = 0;
  586. oid next_prefetched_oid;
  587.  
  588. void
  589. GetNewObjectId(oid_return)
  590.     oid *oid_return;        /* place to return the new object id */
  591. {
  592.     /* ----------------
  593.      *  if we run out of prefetched oids, then we get some
  594.      *  more before handing them out to the caller.
  595.      * ----------------
  596.      */
  597.     
  598.     if (prefetched_oid_count == 0) {
  599.     int oid_block_size = VAR_OID_PREFETCH;
  600.  
  601.     /* ----------------
  602.      *    during bootstrap time, we want to allocate oids
  603.      *    one at a time.  Otherwise there might be some
  604.      *      bootstrap oid's left in the block we prefetch which
  605.      *    would be passed out after the variable relation was
  606.      *    initialized.  This would be bad.
  607.      * ----------------
  608.      */
  609.     if (! RelationIsValid(VariableRelation))
  610.         VariableRelation = heap_openr(VariableRelationName);
  611.     
  612.     /* ----------------
  613.      *    get a new block of prefetched object ids.
  614.      * ----------------
  615.      */
  616.     GetNewObjectIdBlock(&next_prefetched_oid, oid_block_size);
  617.  
  618.     /* ----------------
  619.      *    now reset the prefetched_oid_count.
  620.      * ----------------
  621.      */
  622.     prefetched_oid_count = oid_block_size;
  623.     }
  624.     
  625.     /* ----------------
  626.      *    return the next prefetched oid in the pointer passed by
  627.      *  the user and decrement the prefetch count.
  628.      * ----------------
  629.      */
  630.     if (PointerIsValid(oid_return))
  631.     (*oid_return) = next_prefetched_oid;
  632.     
  633.     next_prefetched_oid++;
  634.     prefetched_oid_count--;
  635. }
  636.